import { _decorator, Component, instantiate, IVec2, Node, Tween, tween, Vec3 } from 'cc';
import { EntityTypeEnum, IBullet, } from '../../Common';
import { BulletStateMachine } from './BulletStateMachine';
import { EntityManager } from '../../Base/EntityManager';
import { WeaponManager } from '../Weapon/WeaponManager';
import { EntityStateEnum, EventEnum } from '../../Enum';
import DataManager from '../../Global/DataManager';
import { rad2Angle } from '../../Utils';
import EventManager from '../../Global/EventManager';
import { ExplosionManager } from '../Explosion/ExplosionManager';
import { ObjectPoolManager } from '../../Global/ObjectPoolManager';
const { ccclass, property } = _decorator;

@ccclass('BulletManager')
export class BulletManager extends EntityManager implements IBullet {
    owner: number;
    position: IVec2;
    direction: IVec2;//子弹类型
    type:EntityTypeEnum
    id:number
    //目标位置
    private targetPos :Vec3
    private tw :Tween<unknown>
    private angle: number;
    
    init(data:IBullet){
        const {id,owner,type}= data 
        this.type=type
        this.owner = owner
        this.id=id

        //每次init的时候都会挂载脚本，所以在对象池调用时要判断有没有这个组件，有就不add了
        this.fsm=this.getComponent(BulletStateMachine)||this.addComponent(BulletStateMachine) 
        this.fsm.init(type)

        //设置默认状态，并且执行其动画
        this.state=EntityStateEnum.Idle

        //初始化时不让节点显示，等renderPos的时候再显示，就不会有瞬移问题了
        this.node.active =false
        this.targetPos = undefined
        this.angle = undefined

        //监听爆炸事件
        EventManager.Instance.on(EventEnum.ExplosionBorn,this.handleExplosionBorn,this)

    }
    /**
     * 爆炸事件处理函数
     * @param id 子弹id
     * @param param1 爆炸位置
     * @returns 
     */
    handleExplosionBorn(id:number,{x,y}:IVec2){
        //判断子弹id是否匹配
        if(id!=this.id){
            return
        }
        
        //将实例化改为从对象池拿
        const explosion=ObjectPoolManager.Instance.get(EntityTypeEnum.Explosion) 
        // explosion.setParent(DataManager.Instance.stage) 对象池中设置了父节点所以不用设置了
        //因为节点是从对象池拿的，所以不一定要addComponent，先getComponent看看有没有挂载脚本
        const em=explosion.getComponent(ExplosionManager)||explosion.addComponent(ExplosionManager) 
        em.init(EntityTypeEnum.Explosion,{x,y})
        
        

        //删除子弹
        EventManager.Instance.off(EventEnum.ExplosionBorn,this.handleExplosionBorn,this)
        DataManager.Instance.bulletMap.delete(this.id)
        // this.node.destroy()不销毁，调用对象处的归还方法
        ObjectPoolManager.Instance.ret(this.node) 
    }
    
    /**
     * battleManager会调用这个方法，把数据渲染到场景中
     */
    render(data:IBullet){
        this.renderPos(data)
        this.renderDire(data)    
    }
    renderPos(data:IBullet){
        const {position}=data
        const newPos = new Vec3 (position.x,position.y)
        //如果targetPos不存在（第一次渲染）
        if(!this.targetPos){
            this.node.active = true
            this.node.setPosition(newPos)
            this.targetPos = new Vec3(newPos)
            //如果目标位置不等于后端传入的值（人物移动）
        }else if(!this.targetPos.equals(newPos)){
            //如果之前有缓动，则停止之前的缓动
            this.tw?.stop()
            this.node.setPosition(this.targetPos)
            this.targetPos.set(newPos)
            this.tw = tween(this.node)
                .to(0.1,{
                    position :this.targetPos,
                })
                .start()
        }
    }
    renderDire(data:IBullet){
        const {direction,position}=data
        //通过虚拟摇杆给的direction来设置子弹的旋转角度
        const side = Math.sqrt(direction.x**2+direction.y**2)
        const angle =direction.x>0? rad2Angle(Math.asin(direction.y/side)):rad2Angle(Math.asin(-direction.y/side))+180

        this.node.setRotationFromEuler(0,0,angle)
    }

}

